<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>imd_blog接口文档</title>
    <!--<link rel="stylesheet" href="https://cdn.bootcss.com/element-ui/2.4.0/theme-chalk/index.css">-->
    <!--<script type="text/javascript" src="http://vuejs.org/js/vue.min.js"></script>-->
    <!--<script src="https://cdn.bootcss.com/element-ui/2.4.0/index.js"></script>-->
    <link rel="stylesheet" href="element-ui.css">
    <script type="text/javascript" src="vue.min.js"></script>
    <script src="element-ui.js"></script>
</head>
<body>
<div id="app">
    <input id="title" type="hidden" v-model="title" />
    <div>
        <el-menu id="header" mode="horizontal">
            <p class="logo-text">{{title}}</p>
            <el-menu-item index="1" disabled class="head-user-box">
                <template slot="title">版本 {{version}}</template>
            </el-menu-item>
            <el-menu-item index="2" class="head-user-box">
                <el-button type="text" @click="rebuild">重新生成文档</el-button>
            </el-menu-item>
            <el-menu-item index="3" class="head-user-box">
                <el-input placeholder="请输入搜索内容" icon="search" v-model="search"></el-input>
            </el-menu-item>
        </el-menu>
    </div>


    <div class="app-menu left-menu" id="left-menu">
        <el-tree ref="apiTree" highlight-current default-expand-all :data="reverseMenus" :props="defaultProps"
                 @current-change="checkChangeHandle" :filter-node-method="filterNode"></el-tree>
    </div>
    <div id="main" v-if="currentApiAction != null" @click="hideTest">
        <h2 class="action-title">{{currentApiAction.title}}</h2>
        <p class="comment">描述:  {{currentApiAction.comment}}</p>
        <p class="uri" v-if="currentApiAction.methods.length > 0">只支持:
            <span v-for="m in currentApiAction.methods">{{m}} </span>
        </p>
        <p class="uri" v-for="uri in currentApiAction.uris">接口地址: {{uri}}</p>
        <p class="return">接口返回: {{currentApiAction.returnDesc}}</p>

        <el-collapse v-model="activeNames">
            <el-collapse-item name="1">
                <template slot="title">
                    <h2>请求参数&nbsp;&nbsp;<i class="header-icon el-icon-edit"></i></h2>
                </template>
                <el-table :data="reverseParam">
                    <el-table-column prop="paramName" label="参数名" width="180"></el-table-column>
                    <el-table-column prop="paramType" label="类型" width="180"></el-table-column>
                    <el-table-column prop="require" label="是否必填" width="100">
                        <template scope="scope">{{scope.row.require ? '是' : '否'}}</template>
                    </el-table-column>
                    <el-table-column prop="paramDesc" label="描述"></el-table-column>
                </el-table>
            </el-collapse-item>

            <el-collapse-item name="2">
                <template slot="title">
                    <h2>返回参数&nbsp;&nbsp;<i class="header-icon el-icon-check"></i></h2>
                </template>
                <el-table :data="reverseResponse">
                    <el-table-column prop="paramName" label="参数名" width="180"></el-table-column>
                    <el-table-column prop="paramType" label="类型" width="180"></el-table-column>
                    <el-table-column prop="require" label="是否必填" width="100">
                        <template scope="scope">{{scope.row.require ? '是' : '否'}}</template>
                    </el-table-column>
                    <el-table-column prop="paramDesc" label="描述"></el-table-column>
                </el-table>
            </el-collapse-item>

            <el-collapse-item name="3" v-if="currentApiAction.respbody != null">
                <template slot="title">
                    <h2>返回例子&nbsp;&nbsp;<i class="header-icon el-icon-view"></i></h2>
                </template>
                <pre>{{reverseRespbody}}</pre>
            </el-collapse-item>
        </el-collapse>
    </div>

    <div id="test" :class="testClassName" v-if="currentApiAction != null && isOnline" @click="showTest">
        <h2>测试</h2>
        <br/>
        <div class="test-main">
            <el-form ref="testForm" :model="testForm" label-width="120px" class="test-form">

                <el-form-item v-if="currentApiAction.methods.length > 0" label="请求方式">
                    <el-radio-group v-model="request.type">
                        <el-radio v-for="m in currentApiAction.methods" :label="m">{{m}}</el-radio>
                    </el-radio-group>
                </el-form-item>

                <el-form-item v-for="param in reverseParam" :label="param.paramName" :prop="param.paramName">
                    <el-input v-model="testForm[param.paramName]"></el-input>
                </el-form-item>

                <el-form-item>
                    <el-button type="primary" @click="onTest">测试</el-button>
                    <el-button @click="resetTestForm">重置</el-button>
                </el-form-item>
            </el-form>

            <h3>返回内容</h3>
            <br/>
            <div class="test-respbody">
                <el-input ref="respbpdy" v-model="testRespbody" type="textarea" :rows="10" placeholder="返回内容..."></el-input>
            </div>
        </div>
    </div>
</div>

<script>
    window.Http = {};
    Http.ajax = function(url, params, method) {

        var config = {
            method: method,
            credentials: 'same-origin',
            headers: {
                'Content-Type': 'application/x-www-form-urlencoded'
            },
            cache: 'no-store'
        };

        var search = '';
        if (params) {
            for (var p in params) {
                if (params[p] == null || typeof(params[p]) === 'undefined') {
                    delete params[p];
                } else {
                    search += p + '=' + encodeURIComponent(params[p]) + '&';
                }
            }

            if (search) {
                search = search.substr(0, search.length - 1);

                if (method.toLocaleLowerCase() === 'get') {
                    if (url.indexOf('?') > 0) {
                        url += '&' + search;
                    } else {
                        url += '?' + search;
                    }
                } else {
                    config.body = search;
                }
            }
        }

        return new Promise(function (resolve, reject) {
            fetch(url, config).then(function (response) {
                return response.text();
            }).then(function (data) {
                resolve(data);
            }).catch(function (e) {
                reject(e);
            });
        });
    }

    /**
     * 发起Post请求
     *
     * @param {String} url 请求地址
     * @param {object} params 请求参数
     */
    Http.Post = function(url, params) {
        return Http.ajax(url, params, 'POST');
    }

    /**
     * 发起Get请求
     *
     * @param {String} url 请求地址
     * @param {Object} params 请求参数
     */
    Http.Get = function(url, params) {
        return Http.ajax(url, params, 'GET');
    }
</script>
<script>
    new Vue({
        el: '#app',
        data() {
            return {
                search: '',
                activeNames: ['1', '2', '3'],
                radio2: '1',
                testRespbody: '',
                apiModules: [],
                testForm : {},
                isOnline : true,
                testClassName : 'test-off',
                defaultProps: {
                    children: 'children',
                    label: 'label'
                },
                request : {
                    type : 'GET'
                },
                title : 'XDoc 接口文档',
                version: 'v1.0',
                currentApiModule: null,
                currentApiAction: null
            }
        },

        mounted() {
            if (!window.apis) {
                var self = this;
                fetch('apis').then(function(response) {
                    return response.json();
                }).then(function(data) {
                    if (typeof(data) == 'string') {//兼容后端返回数据出问题
                        data = JSON.parse(data);
                    }
                    self.fullData(data);

                    //设置title
                    var titleEl = document.getElementById("title");
                    if (titleEl && titleEl.value) {
                        document.title = titleEl.value;
                    }
                }).catch(function(e) {
                    self.$message.error('系统错误,请求api列表 接口失败');
                });
            } else {
                this.isOnline = false;
                this.fullData(window.apis);
            }
        },

        computed: {
            reverseMenus() {
                var menu = [];
                var id = 1;
                for (var i = 0; i < this.apiModules.length; i++) {
                    var apiModule = this.apiModules[i];

                    var children = [];

                    for (var j = 0; j < apiModule.apiActions.length; j++) {
                        var apiAction = apiModule.apiActions[j];
                        apiAction.id = id++;//赋值一个ID
                        children.push({
                            label: apiAction.title,
                            id: apiAction.id
                        });
                    }

                    var item = {
                        label: apiModule.comment,
                        children: children,
                        data: apiAction
                    };
                    menu.push(item);
                }

                return menu;
            },

            reverseParam() {
                if (this.currentApiAction) {
                    var names = {};
                    var data = [];
                    this.testForm = {};
                    for (var i = 0; i < this.currentApiAction.params.length; i++) {
                        var par = this.currentApiAction.params[i];
                        data.push(par);
                        this.$set(this.testForm, par.paramName, '');//动态绑定监控

                        names[par.paramName] = par.paramName;
                    }

                    if (this.currentApiAction.paramObjs) {
                        for (var i = 0; i < this.currentApiAction.paramObjs.length; i++) {
                            var paramObj = this.currentApiAction.paramObjs[i];
                            if (!paramObj.fieldInfos) {
                                continue;
                            }

                            for (var j = 0; j < paramObj.fieldInfos.length; j++) {
                                var fieldInfo = paramObj.fieldInfos[j];
                                if (names[fieldInfo.name]) {
                                    //@param上已经有了,则不再使用@paramObj中的
                                    continue;
                                }
                                data.push({
                                    paramName : fieldInfo.name,
                                    paramDesc: fieldInfo.comment,
                                    require: fieldInfo.require,
                                    paramType: fieldInfo.simpleTypeName
                                });
                                this.$set(this.testForm, fieldInfo.name, '');//动态绑定监控
                            }
                        }
                    }

                    return data;
                }
            },

            reverseResponse() {
                var names = {};

                var data = [];

                if (this.currentApiAction && this.currentApiAction.respParam && this.currentApiAction.respParam.length > 0) {
                    for (var i = 0; i < this.currentApiAction.respParam.length; i++) {
                        var par = this.currentApiAction.respParam[i];
                        names[par.paramName] = par.paramName;
                        data.push({
                            paramName: par.paramName,
                            paramDesc: par.paramDesc,
                            paramType: par.paramType,
                            require: par.require
                        });
                    }
                }

                if (this.currentApiAction && this.currentApiAction.returnObj) {

                    for (var i = 0; i < this.currentApiAction.returnObj.fieldInfos.length; i++) {
                        var par = this.currentApiAction.returnObj.fieldInfos[i];

                        if (names[par.name] != null) {
                            //已经有@resp注解进行了覆盖,就不再采纳@return中的
                            continue;
                        }

                        data.push({
                            paramName: par.name,
                            paramDesc: par.comment,
                            paramType: par.simpleTypeName,
                            require : par.require
                        });
                    }
                }
                return data;
            },

            reverseRespbody() {
                if (this.currentApiAction && this.currentApiAction.respbody) {
                    try {
                        var obj = JSON.parse(this.currentApiAction.respbody);
                        return JSON.stringify(obj, null, 4);
                    } catch(e) {

                    }
                    return this.currentApiAction.respbody;
                }
            }
        },

        methods: {

            fullData(data) {
                if (data.properties && data.properties.title != null) {
                    this.title = data.properties.title;
                }
                if (data.properties && data.properties.version != null) {
                    this.version = data.properties.version;
                }
                this.apiModules = data.apiModules;
                if (this.apiModules.length > 0 && this.apiModules[0].apiActions.length > 0) {
                    this.currentApiModule = this.apiModules[0];
                    this.currentApiAction = this.apiModules[0].apiActions[0];
                    if (this.currentApiAction.methods.length > 0) {
                        this.request.type = this.currentApiAction.methods[0];
                    }
                }
            },

            checkChangeHandle(data, checked, indeterminate) {
                var array = this.findModuleAndActionById(data.id);
                if (array) {
                    this.currentApiModule = array[0];
                    this.currentApiAction = array[1];
                    if (this.currentApiAction.methods.length > 0) {
                        this.request.type = this.currentApiAction.methods[0];
                    } else {
                        this.request.type = 'get';
                    }
                    this.resetTestForm();
                }
            },

            findModuleAndActionById(id) {
                for (var i = 0; i < this.apiModules.length; i++) {
                    var apiModule = this.apiModules[i];

                    for (var j = 0; j < apiModule.apiActions.length; j++) {
                        if (apiModule.apiActions[j].id == id) {
                            return [apiModule, apiModule.apiActions[j]]
                        }
                    }
                }
            },

            filterNode(value, data) {
                if (!value) return true;
                return data.label.indexOf(value) !== -1;
            },

            showTest() {
                this.testClassName = 'test-on';
            },

            hideTest() {
                this.testClassName = 'test-off';
            },

            rebuild() {
                window.location = 'rebuild.html';
            },

            resetTestForm() {
                if (this.$refs.testForm) {
                    this.$refs.testForm.resetFields();
                }
            },

            onTest() {
                var self = this;

                var uri = '';

                if (this.currentApiAction.uris.length > 0) {
                    uri += '/web/' + this.currentApiAction.uris[0];
                }
                var requestType = this.request.type.toLocaleLowerCase();

                console.log('请求方式:', requestType, '请求数据:', this.testForm);

                Http.ajax(uri, this.testForm, requestType).then((data) => {
                    self.testRespbody = data;
                }).catch((e) => {
                    console.log(e);
                    window.resp = e;
                    self.$message.error('系统错误:' + e);
                });
            }
        },

        watch : {
            search(val) {
                this.$refs.apiTree.filter(val);
            },
        }
    })
</script>
</body>

<style>
    * {
        padding: 0;
        margin: 0;
        font-family: Helvetica Neue,Helvetica,PingFang SC,Hiragino Sans GB,Microsoft YaHei,SimSun,sans-serif;
    }

    .logo-text {
        float: left;
        height: 60px;
        color: hsla(0,0%,40%,.7);
        line-height: 60px;
        padding-left: 32px;
		font-size: 22px;
    }

    .left-menu {
        width: 400px;
        border-right: solid 2px #EAEDF1;
        display: block;
        position: fixed;
        bottom: 0px;
        z-index: 102;
        top: 60px;
        padding-top: 7px;
        overflow-x: hidden;
    }

    #header {
        height: 60px;
        z-index: 200;
    }

    #header .head-user-box {
        float: right;
    }

    .el-tree {
        border: 0px solid #d1dbe5
    }

    #main {
        left: 403px;
        padding: 20px 70px 0 20px;
        width: auto;
        position: absolute;
        top: 60px;
        bottom: 0px;
        right: 0px;
        overflow: auto;
    }

    #main .comment, .uri, .return {
        padding: 20px;
    }

    #test {
        right: 0px;
        padding: 20px 20px;
        position: absolute;
        top: 60px;
        bottom: 0px;
        overflow: auto;
        background-color:#FFF;
        border-left : 2px solid #eef1f6;
        transition:all .2s ease;
        -webkit-transition:all .2s ease;
        z-index : 1;
    }

    .test-off {
        width : 20px;
        cursor: pointer;
    }

    .test-on {
        width : 800px;
        cursor: auto;
    }

    .test-off .test-main {
        display : none;
    }

    .test-on .test-main {
        display : auto;
    }

    .test-form {
        width : 80%;
    }

    .test-respbody {
        padding-left : 50px;
        width : 700px;
    }

    .action-title {
        background: #EEE;
        height: 50px;
        line-height: 50px;
        padding-left: 10px;
        border-radius: 4px;
    }
</style>

</html>
